home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 429_01 / chess12 / cplayer.cpp < prev    next >
C/C++ Source or Header  |  1994-03-30  |  6KB  |  222 lines

  1. #include <limits.h>
  2.  
  3. #include "brdsize.hpp"
  4. #include "chess.hpp"
  5. #include "cplayer.hpp"
  6. #include "chessui.hpp"
  7.  
  8. // returns a measurement of how much of the board is "covered" by
  9. // the pieces of a given player.  lots of extra points are given
  10. // for "covering" the location around the opponent's king
  11. LOCAL int coverage
  12.   (
  13.     const BOARD &board,
  14.     PIECECOLOR color,
  15.     POSITION whereEnemyKing
  16.   )
  17.   {
  18.     unsigned char map[NUMROWS][NUMCOLS];
  19.     // bit flags for elements of map
  20.     const unsigned char KINGAREA = 1;
  21.     const unsigned char COVERED = 2;
  22.     POSITION where;
  23.     POSITIONLIST moves;
  24.     int m, result = 0;
  25.  
  26.     // initialize map
  27.     for (where.row = 0; where.row < NUMROWS; where.row++)
  28.       for (where.col = 0; where.col < NUMCOLS; where.col++)
  29.         map[where.row][where.col] = 0;
  30.  
  31.     // set covered flag on all covered locations
  32.     for (where.row = 0; where.row < NUMROWS; where.row++)
  33.       for (where.col = 0; where.col < NUMCOLS; where.col++)
  34.     {
  35.       if (board.whatPiece(where))
  36.         if ((board.whatPiece(where)->whatColor() == color) &&
  37.             (board.whatPiece(where)->whatType() != TYPEPAWN))
  38.           {
  39.         board.whatPiece(where)->legalMoves(where, board, moves);
  40.         for (m = 0; m < moves.nMoves; m++)
  41.           map[moves.end[m].row][moves.end[m].col] = COVERED;
  42.           }
  43.     }
  44.  
  45.     // flag locations to which enemy king could move
  46.     board.whatPiece(whereEnemyKing)->
  47.       legalMoves(whereEnemyKing, board, moves);
  48.     for (m = 0; m < moves.nMoves; m++)
  49.       map[moves.end[m].row][moves.end[m].col] |= KINGAREA;
  50.  
  51.     // accumulate coverage points
  52.     for (where.row = 0; where.row < NUMROWS; where.row++)
  53.       for (where.col = 0; where.col < NUMCOLS; where.col++)
  54.     {
  55.           if (map[where.row][where.col] & COVERED)
  56.         {
  57.           if (map[where.row][where.col] & KINGAREA)
  58.         result += 20;
  59.           else
  60.         result += 1;
  61.         }
  62.     }
  63.  
  64.     return(result);
  65.   }
  66.  
  67. LOCAL POSITION whereKing
  68.   (
  69.     const BOARD &board,
  70.     PIECECOLOR color
  71.   )
  72.   {
  73.     POSITION where;
  74.  
  75.     for (where.row = 0; ; where.row++)
  76.       for (where.col = 0; where.col < NUMCOLS; where.col++)
  77.     {
  78.       if (board.whatPiece(where))
  79.         if (board.whatPiece(where)->whatColor() == color)
  80.           if (board.whatPiece(where)->whatType() == TYPEKING)
  81.         return(where);
  82.     }
  83.   }
  84.  
  85. // positive difference between two integers
  86. LOCAL inline int absDiff(int a, int b)
  87.   {
  88.     a -= b;
  89.     return(a < 0 ? -a : a);
  90.   }
  91.  
  92. // the change in difference from a goal value between a starting
  93. // and an ending value
  94. LOCAL int oneDimHowClose(int start, int end, int goal)
  95.   {
  96.     int a = absDiff(start, goal);
  97.     int diff = a - absDiff(end, goal);
  98.  
  99.     if ((a < 2) && (diff > 0))
  100.       return(0);
  101.  
  102.     return(diff);
  103.   }
  104.  
  105. // the change in "threat" metric caused by a given piece moving from
  106. // a starting position to an ending position in terms of trying to
  107. // threaten a goal position
  108. LOCAL int threatChange
  109.   (
  110.     POSITION start,
  111.     POSITION end,
  112.     POSITION goal,
  113.     PIECE *p
  114.   )
  115.   {
  116.     if (p->whatType() == TYPEPAWN)
  117.       return(absDiff(start.col, end.col) * 2);
  118.  
  119.     return(oneDimHowClose(start.row, end.row, goal.row) +
  120.            oneDimHowClose(start.col, end.col, goal.col));
  121.   }
  122.  
  123. // for a given list of moves, find the one that best improves the
  124. // "development" of a player's pieces.  development is a combination
  125. // of covering alot of the board, getting pieces close to the enemy's
  126. // king, and restricting the enemy king's movement.
  127. LOCAL int bestDevelopMove 
  128.   (
  129.     BOARD &board,
  130.     PIECECOLOR moveColor,
  131.     BESTMOVES &bestMoves
  132.   )
  133.   {
  134.     POSITION whereEnemyKing = whereKing(board, OtherColor(moveColor));
  135.     int testMetric, bestMetric = INT_MIN;
  136.     int bestIndex, testIndex;
  137.     MOVEUNDODATA undoData;
  138.  
  139.     for (testIndex = 0; testIndex < bestMoves.nMoves; testIndex++)
  140.       {
  141.     // engage in castlephilia
  142.     if (bestMoves.move[testIndex].type != NORMALMOVE)
  143.       return(testIndex);
  144.  
  145.     board.doMove
  146.       (
  147.         bestMoves.move[testIndex].start,
  148.         bestMoves.move[testIndex].end,
  149.         undoData
  150.       );
  151.  
  152.     if (bestMoves.move[testIndex].promoteType != TYPENOPIECE)
  153.       board.promote(bestMoves.move[testIndex].end,
  154.             bestMoves.move[testIndex].promoteType);
  155.  
  156.     testMetric = undoData.capturedPiece ?
  157.              undoData.capturedPiece->whatValue() * 16 : 0;
  158.     testMetric += coverage(board, moveColor, whereEnemyKing) +
  159.               threatChange
  160.                 (
  161.               bestMoves.move[testIndex].start,
  162.               bestMoves.move[testIndex].end,
  163.               whereEnemyKing,
  164.               board.whatPiece(bestMoves.move[testIndex].end)
  165.                 ) * 4;
  166.  
  167.     if (testMetric > bestMetric)
  168.       {
  169.         bestIndex = testIndex;
  170.         bestMetric = testMetric;
  171.       }
  172.  
  173.     if (bestMoves.move[testIndex].promoteType != TYPENOPIECE)
  174.       board.restorePawn(bestMoves.move[testIndex].end);
  175.  
  176.     board.undoMove
  177.       (
  178.         bestMoves.move[testIndex].end,
  179.         bestMoves.move[testIndex].start,
  180.         undoData
  181.       );
  182.       }
  183.  
  184.     return(bestIndex);
  185.   }
  186.  
  187. GAMESTATUS COMPUTERPLAYER::play(BOARD &board) const
  188.   {
  189.     BOARDMETRIC metric;
  190.     BESTMOVES bestMoves;
  191.     int best;
  192.  
  193.     ChessUI.thinkingMessage(whatColor());
  194.     board.findBestMoves(lookAhead, whatColor(), metric, &bestMoves);
  195.     if (metric.kingSituation[whatColor()] != KINGOK)
  196.       {
  197.     // see if checkmate/stalemate current or predicted
  198.     if (lookAhead > 2)
  199.       board.findBestMoves(2, whatColor(), metric, &bestMoves);
  200.  
  201.     if (metric.kingSituation[whatColor()] == KINGLOST)
  202.       {
  203.         ChessUI.clearMessage();
  204.         ChessUI.mated(whatColor());
  205.         return(GAMEOVER);
  206.       }
  207.     else if (metric.kingSituation[whatColor()] == STALEMATE)
  208.       {
  209.         ChessUI.clearMessage();
  210.         ChessUI.staleMated(whatColor());
  211.         return(GAMEOVER);
  212.       }
  213.       }
  214.  
  215.     best = bestDevelopMove(board, whatColor(), bestMoves);
  216.  
  217.     if (!ChessUI.computerMove(board, whatColor(),
  218.                               bestMoves.move[best]))
  219.       return(GAMEOVER);
  220.     return(GAMECONTINUE);
  221.   }
  222.